﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------
/*
	TODO:
		- static buffer for dynamic objects
*/

#ifndef _UXS_FUNCTION_H
#define _UXS_FUNCTION_H

#pragma once

#include "../BaseTypes/Types.h"
#include "../CompileTime/TTypeInfo.h"
#include "../CompileTime/TypeTraits.h"
#include "../CompileTime/TemplateUtils.h"
#include "../CompileTime/TypeList.h"
#include "../Containers/TSet.h"
#include "TAutoPtr.h"
#include "TSimplePtr.h"
#include "TBufferedPtr.h"

namespace UX_STL
{
namespace UXTypes
{
	
#define _STATICFUNCTION_TYPE_DECL(	_template_params, \
									_template_override, \
									_template_types, \
									_ret, \
									_decl_params, \
									_decl_params_ref_with_comma, \
									_member_params, \
									_args_to_members, \
									_members_move_ctor, \
									_arg_params, \
									_func_args_with_comma ) \
	namespace _types_hidden_ { \
		\
		/* Function Implementation */ \
		template <usize BufSize, _template_params> \
		struct TStaticFunctionImpl _template_override : TFunction< _ret, BufSize >::Interface \
		{ \
		public: \
			typedef _ret (* PFunction_t) ( _decl_params ); \
			typedef TStaticFunctionImpl< BufSize, _template_types >			Self; \
			typedef typename TFunction< _ret, BufSize >::interface_ptr_t	ptr_t; \
			\
		private: \
			PFunction_t		_func; \
			_member_params \
			\
		public: \
			TStaticFunctionImpl (PFunction_t func _decl_params_ref_with_comma): \
				_func(func) _args_to_members \
			{} \
			\
			RVALUE_REFERENCE_ONLY( \
				TStaticFunctionImpl (TStaticFunctionImpl &&o): \
					_func(o._func) _members_move_ctor \
				{} \
			) \
			\
			bool		IsValid ()			const override	{ return _func != null; } \
			_ret		Call ()				const override	{ return _func( _arg_params ); } \
			void		CloneTo (ptr_t &p)	const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			RVALUE_REFERENCE_ONLY( void	MoveTo (ptr_t &p)	  override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( ToRValueRef( *this ) ) ); } ) \
			TypeId_t	TypeId ()			const override	{ return TypeIdOf( *this ); } \
			usize		Size ()				const override	{ return sizeof( this ); } \
		}; \
	} \
	\
	namespace FunctionBuilder \
	{ \
		template <_template_params> \
		struct Type < _ret (*) (_decl_params) > \
		{ \
			typedef _ret (* PFunction_t) (_decl_params); \
			\
			template <usize BufSize> \
			static void Create (OUT TFunction< _ret, BufSize > &fn, PFunction_t func _decl_params_ref_with_comma) \
			{ \
				typedef _types_hidden_::TStaticFunctionImpl< BufSize, _template_types >		fn_impl_t; \
				fn._func._SetPtr( new ( fn._func._GetBuffer< sizeof(fn_impl_t) >() ) fn_impl_t( func _func_args_with_comma ) ); \
			} \
		}; \
		\
		template <usize BufSize, _template_params> \
		inline void Create (OUT TFunction< _ret, BufSize > &fn, _ret (* func) (_decl_params) _decl_params_ref_with_comma) \
		{ \
			Type< _ret (*)(_decl_params) >::Create( fn, func _func_args_with_comma ); \
		} \
	}
	
#define _STATICDELEGATE_TYPE_DECL(	_template_params, \
									_template_override, \
									_template_types, \
									_ret, \
									_decl_params, \
									_decl_params_ref, \
									_func_args ) \
	namespace _types_hidden_ { \
		\
		/* Delegate Interface */ \
		template <_template_params> \
		struct TDelegateInterface < _ret (_decl_params) > \
		{ \
			typedef TDelegateInterface< _ret (_decl_params) >					Interface; \
			typedef BufferedPtr< Interface, UX_OPT_DELEGATE_INTERFACE_SIZE >	ptr_t; \
			\
			virtual ~TDelegateInterface () {} \
			virtual bool		IsValid ()				const = 0; \
			virtual _ret		Call (_decl_params_ref)	const = 0; \
			virtual void		CloneTo (ptr_t &)		const = 0; \
			virtual TypeId_t	TypeId ()				const = 0; \
			virtual usize		Size ()					const = 0; \
			\
			bool Cmp (const Interface *p) const \
			{ \
				const usize size = Size(); \
				return	( size == p->Size() ) and \
						( TypeId() == p->TypeId() ) and \
						MemCmp( (void *)this, (void *)p, size ) == 0; \
			} \
			\
			bool Less (const Interface *p) const \
			{ \
				const usize		size0 = Size(); \
				const usize		size1 = p->Size(); \
				const TypeId_t	type0 = TypeId(); \
				const TypeId_t	type1 = p->TypeId(); \
				\
				if ( type0 == type1 ) { \
					if ( size0 == size1 ) \
						return MemCmp( (void *)this, (void *)p, size0 ) < 0; \
					else \
						return size0 < size1; \
				} \
				return type0 < type1; \
			} \
			\
			bool Greater (const Interface *p) const \
			{ \
				const usize		size0 = Size(); \
				const usize		size1 = p->Size(); \
				const TypeId_t	type0 = TypeId(); \
				const TypeId_t	type1 = p->TypeId(); \
				\
				if ( type0 == type1 ) { \
					if ( size0 == size1 ) \
						return MemCmp( (void *)this, (void *)p, size0 ) > 0; \
					else \
						return size0 > size1; \
				} \
				return type0 > type1; \
			} \
		}; \
	} \
	\
	namespace DelegateBuilder \
	{ \
		template <_template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, _ret (*func) (_decl_params)); \
		\
		template <typename C, typename CP, _template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params)); \
		\
		template <typename C, typename CP, _template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params) const); \
	} \
	\
	/* Delegate */ \
	template <_template_params> \
	struct TDelegate < _ret (_decl_params) > \
	{ \
		template <_template_params> \
		friend void DelegateBuilder::Create (OUT TDelegate < _ret (_decl_params) > &del, _ret (*func) (_decl_params)); \
		\
		template <typename C, typename CP, _template_params> \
		friend void DelegateBuilder::Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params)); \
		\
		template <typename C, typename CP, _template_params> \
		friend void DelegateBuilder::Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params) const); \
	\
	public: \
		typedef _ret (* PFunction_t) (_decl_params); \
		typedef _types_hidden_::TDelegateInterface< _ret (_decl_params) >	Interface; \
		typedef TDelegate< _ret (_decl_params) >							Self; \
		typedef typename CompileTime::TypeList20< _template_types >::type	arg_types_t; \
		typedef typename Interface::ptr_t									interface_ptr_t; \
		\
	private: \
		interface_ptr_t		_func; \
		\
	public: \
		TDelegate () \
		{} \
		\
		\
		TDelegate (const Self &other) \
		{ \
			if ( other._func.IsNotNull() ) { \
				other._func->CloneTo( _func ); \
			} \
		} \
		\
		\
		Self & operator = (const Self &right) \
		{ \
			if ( right._func.IsNotNull() ) { \
				right._func->CloneTo( _func ); \
			} \
			return *this; \
		} \
		\
		\
		bool	IsValid ()						const	{ return _func.IsNotNull() and _func->IsValid(); } \
		\
		_ret Call (_decl_params_ref)			const	{ ASSERT( IsValid() );  return _func->Call(_func_args); } \
		_ret SafeCall (_decl_params_ref)		const	{ return IsValid() ? _func->Call(_func_args) : _ret(); } \
		\
		_ret operator () (_decl_params_ref)		const	{ ASSERT( IsValid() );  return _func->Call(_func_args); } \
		\
		bool operator == (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Cmp( right._func.ptr() );  } \
		bool operator <  (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Less( right._func.ptr() ); } \
		bool operator >  (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Greater( right._func.ptr() ); } \
		bool operator != (const Self &right)	const	{ return not (*this == right); } \
		bool operator <= (const Self &right)	const	{ return not (*this >  right); } \
		bool operator >= (const Self &right)	const	{ return not (*this <  right); } \
	}; \
	\
	namespace _types_hidden_ { \
		\
		/* Delegate Implementation */ \
		template <_template_params> \
		struct TStaticDelegateImpl _template_override : TDelegateInterface< _ret (_decl_params) > \
		{ \
		public: \
			typedef _ret (* PFunction_t) (_decl_params); \
			typedef TStaticDelegateImpl< _template_types >		Self; \
			typedef TDelegateInterface< _ret (_decl_params) >	Interface; \
			\
		private: \
			PFunction_t		_func; \
			\
		public: \
			explicit \
			TStaticDelegateImpl (PFunction_t func): _func(func) {} \
			\
			bool		IsValid ()				const override	{ return _func != null; } \
			_ret		Call (_decl_params_ref)	const override	{ return _func(_func_args); } \
			void		CloneTo (ptr_t &p)		const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			TypeId_t	TypeId ()				const override	{ return TypeIdOf( *this ); } \
			usize		Size ()					const override	{ return sizeof(this); } \
		}; \
	} \
	namespace DelegateBuilder \
	{ \
		template <_template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, _ret (*func) (_decl_params)) \
		{ \
			typedef _types_hidden_::TStaticDelegateImpl< _template_types >	del_impl_t; \
			del._func._SetPtr( new ( del._func._GetBuffer< sizeof(del_impl_t) >() ) del_impl_t( func ) ); \
		} \
		\
		template <_template_params> \
		inline typename RValueRef< TDelegate < _ret (_decl_params) > >::type  Create (_ret (*func) (_decl_params)) \
		{ \
			TDelegate < _ret (_decl_params) >	del; \
			Create( del, func ); \
			return ToRValueRef( del ); \
		} \
	}

			
#define _EVENTDELEGATE_TYPE_DECL(	_template_params, \
									_ret, \
									_decl_params, \
									_decl_params_ref, \
									_func_args ) \
	/* Event Delegate Implementation */ \
	template <_template_params> \
	struct TEventDelegate < _ret (_decl_params) > \
	{ \
	public: \
		typedef _ret (* PFunction_t) ( _decl_params ); \
		typedef TDelegate< _ret (_decl_params) >	delegate_t; \
		typedef TEventDelegate< PFunction_t >		Self; \
		typedef set< delegate_t >					delegate_set_t; \
		\
	private: \
		delegate_set_t	_delegates; \
		\
	public: \
		TEventDelegate ()						{} \
		\
		TEventDelegate (const Self &other) : _delegates(other._delegates) {} \
		\
		void Add (const delegate_t &del)		{ _delegates.AddOrReplace( del ); } \
		\
		void Remove (const delegate_t &del)		{ _delegates.Erase( del ); } \
		\
		template <typename C, typename CP> \
		void Add (const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			return Add( DelegateBuilder::Create( ptr, func ) ); \
		} \
		\
		void Add (_ret (*func) (_decl_params)) \
		{ \
			return Add( DelegateBuilder::Create( func ) ); \
		} \
		\
		template <typename C, typename CP> \
		void Remove (const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			return Remove( DelegateBuilder::Create( ptr, func ) ); \
		} \
		\
		void Remove (_ret (*func) (_decl_params)) \
		{ \
			return Remove( DelegateBuilder::Create( func ) ); \
		} \
		\
		void Clear () \
		{ \
			_delegates.Clear(); \
		} \
		\
		void Call (_decl_params_ref)		const	{ FOR( i, _delegates ) { _delegates[i].Call( _func_args ); } } \
		\
		void operator () (_decl_params_ref)	const 	{ FOR( i, _delegates ) { _delegates[i].Call( _func_args ); } } \
		\
		usize Count ()						const	{ return _delegates.Count(); } \
		\
		bool Empty()						const	{ return _delegates.Empty(); } \
		\
		delegate_t const & Get (usize i)	const	{ return _delegates[i]; } \
	}; \
	\
	template <_template_params> \
	struct TEventDelegate < TDelegate< _ret (_decl_params) > > \
	{ \
	public: \
		typedef _ret (* PFunction_t) ( _decl_params ); \
		typedef TDelegate< _ret (_decl_params) >	delegate_t; \
		typedef TEventDelegate< delegate_t >		Self; \
		typedef set< delegate_t >					delegate_set_t; \
		\
	private: \
		delegate_set_t	_delegates; \
		\
	public: \
		TEventDelegate ()						{} \
		\
		TEventDelegate (const Self &other) : _delegates(other._delegates) {} \
		\
		void Add (const delegate_t &del)		{ _delegates.AddOrReplace( del ); } \
		\
		void Remove (const delegate_t &del)		{ _delegates.Erase( del ); } \
		\
		template <typename C, typename CP> \
		void Add (const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			return Add( DelegateBuilder::Create( ptr, func ) ); \
		} \
		\
		void Add (_ret (*func) (_decl_params)) \
		{ \
			return Add( DelegateBuilder::Create( func ) ); \
		} \
		\
		template <typename C, typename CP> \
		void Remove (const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			return Remove( DelegateBuilder::Create( ptr, func ) ); \
		} \
		\
		void Remove (_ret (*func) (_decl_params)) \
		{ \
			return Remove( DelegateBuilder::Create( func ) ); \
		} \
		\
		void Clear () \
		{ \
			_delegates.Clear(); \
		} \
		\
		void Call (_decl_params_ref)		const	{ FOR( i, _delegates ) { _delegates[i].Call( _func_args ); } } \
		\
		void operator () (_decl_params_ref)	const 	{ FOR( i, _delegates ) { _delegates[i].Call( _func_args ); } } \
		\
		usize Count ()						const	{ return _delegates.Count(); } \
		\
		bool Empty()						const	{ return _delegates.Empty(); } \
		\
		delegate_t const & Get (usize i)	const	{ return _delegates[i]; } \
	};


#define _MEMBERFUNCTION_TYPE_DECL(	_template_params, \
									_template_override, \
									_template_types, \
									_ret, \
									_decl_params, \
									_decl_params_ref_with_comma, \
									_member_params, \
									_args_to_members, \
									_members_move_ctor, \
									_arg_params, \
									_func_args_with_comma ) \
	namespace _types_hidden_ { \
		\
		/* Function Implementation */ \
		template <typename C, typename CP, usize BufSize, _template_params> \
		struct TMemberFunctionImpl _template_override : TFunction< _ret, BufSize >::Interface \
		{ \
		public: \
			typedef _ret (C:: *PFunction_t)(_decl_params); \
			typedef TMemberFunctionImpl< C, CP, BufSize, _template_types >		Self; \
			typedef typename TFunction< _ret, BufSize >::interface_ptr_t		ptr_t; \
		\
		private: \
			PFunction_t		_func; \
			CP				_classPtr; \
			_member_params \
		\
		public: \
			TMemberFunctionImpl (const CP &ptr, PFunction_t func _decl_params_ref_with_comma): \
				_func(func), _classPtr(ptr) _args_to_members \
			{} \
			\
			RVALUE_REFERENCE_ONLY( \
				TMemberFunctionImpl (TMemberFunctionImpl &&o): \
					_func(o._func), _classPtr( ToRValueRef( o._classPtr ) ) _members_move_ctor \
				{} \
			) \
			\
			bool		IsValid ()			const override	{ return _func != null and _classPtr != null; } \
			_ret		Call ()				const override	{ return ((*_classPtr).*_func)( _arg_params ); } \
			void		CloneTo (ptr_t &p)	const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			RVALUE_REFERENCE_ONLY( void	MoveTo (ptr_t &p)	  override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( ToRValueRef( *this ) ) ); } ) \
			TypeId_t	TypeId ()			const override	{ return TypeIdOf( *this ); } \
			usize		Size ()				const override	{ return sizeof( this ); } \
		}; \
		\
		/* Function Implementation */ \
		template <typename C, typename CP, usize BufSize, _template_params> \
		struct TMemberConstFunctionImpl _template_override : TFunction< _ret, BufSize >::Interface \
		{ \
		public: \
			typedef _ret (C:: *PFunction_t)(_decl_params) const; \
			typedef TMemberConstFunctionImpl< C, CP, BufSize, _template_types >		Self; \
			typedef typename TFunction< _ret, BufSize >::interface_ptr_t			ptr_t; \
		\
		private: \
			PFunction_t		_func; \
			CP				_classPtr; \
			_member_params \
		\
		public: \
			TMemberConstFunctionImpl (const CP &ptr, PFunction_t func _decl_params_ref_with_comma): \
				_func(func), _classPtr(ptr) _args_to_members \
			{} \
			\
			RVALUE_REFERENCE_ONLY( \
				TMemberConstFunctionImpl (TMemberConstFunctionImpl &&o): \
					_func(o._func), _classPtr( ToRValueRef( o._classPtr ) ) _members_move_ctor \
				{} \
			) \
			\
			bool		IsValid ()			const override	{ return _func != null and _classPtr != null; } \
			_ret		Call ()				const override	{ return ((*_classPtr).*_func)( _arg_params ); } \
			void		CloneTo (ptr_t &p)	const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			RVALUE_REFERENCE_ONLY( void	MoveTo (ptr_t &p)	  override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( ToRValueRef( *this ) ) ); } ) \
			TypeId_t	TypeId ()			const override	{ return TypeIdOf( *this ); } \
			usize		Size ()				const override	{ return sizeof( this ); } \
		}; \
	} \
	\
	namespace FunctionBuilder \
	{ \
		template <typename C, _template_params> \
		struct Type < _ret (C:: *) (_decl_params) > \
		{ \
			typedef _ret (C:: *PFunction_t) (_decl_params); \
			\
			template <typename CP, usize BufSize> \
			static void Create (OUT TFunction< _ret, BufSize > &fn, const CP &ptr, PFunction_t func _decl_params_ref_with_comma) \
			{ \
				typedef _types_hidden_::TMemberFunctionImpl< C, CP, BufSize, _template_types >	fn_impl_t; \
				fn._func._SetPtr( new ( fn._func._GetBuffer< sizeof(fn_impl_t) >() ) fn_impl_t( ptr, func _func_args_with_comma ) ); \
			} \
		}; \
		\
		template <typename C, _template_params> \
		struct Type < _ret (C:: *) (_decl_params) const > \
		{ \
			typedef _ret (C:: *PFunction_t) (_decl_params) const; \
			\
			template <typename CP, usize BufSize> \
			static void Create (OUT TFunction< _ret, BufSize > &fn, const CP &ptr, PFunction_t func _decl_params_ref_with_comma) \
			{ \
				typedef _types_hidden_::TMemberConstFunctionImpl< C, CP, BufSize, _template_types >	fn_impl_t; \
				fn._func._SetPtr( new ( fn._func._GetBuffer< sizeof(fn_impl_t) >() ) fn_impl_t( ptr, func _func_args_with_comma ) ); \
			} \
		}; \
		\
		template <typename C, typename CP, usize BufSize, _template_params> \
		inline void Create (OUT TFunction< _ret, BufSize > &fn, const CP &ptr, _ret (C:: *func) (_decl_params) _decl_params_ref_with_comma) \
		{ \
			Type< _ret (C:: *)(_decl_params) >::Create( fn, ptr, func _func_args_with_comma ); \
		} \
		\
		template <typename C, typename CP, usize BufSize, _template_params> \
		inline void Create (OUT TFunction< _ret, BufSize > &fn, const CP &ptr, _ret (C:: *func) (_decl_params) const _decl_params_ref_with_comma) \
		{ \
			Type< _ret (C:: *)(_decl_params) const >::Create( fn, ptr, func _func_args_with_comma ); \
		} \
	}
	
#define _MEMBERDELEGATE_TYPE_DECL(	_template_params, \
									_template_override, \
									_template_types_with_comma, \
									_template_types_var_with_comma, \
									_ret, \
									_decl_params, \
									_decl_params_ref, \
									_func_args, \
									_uid ) \
	namespace _types_hidden_ { \
		\
		/* Delegate Interface */ \
		template <typename C, _template_params> \
		struct TDelegateInterface##_uid : TDelegateInterface< _ret (_decl_params) > \
		{ \
		}; \
		\
		/* Delegate Implementation */ \
		template <typename C, _template_params> \
		struct TMemberDelegateImpl _template_override : \
			TDelegateInterface##_uid< typename RawPointer< C >::type _template_types_var_with_comma > \
		{ \
		public: \
			typedef typename RawPointer<C>::type								class_t; \
			typedef _ret (class_t:: * PFunction_t)( _decl_params ); \
			typedef TMemberDelegateImpl< C _template_types_with_comma >			Self; \
			typedef typename RawPointer< C >::ptr_t								class_ptr_t; \
			typedef TDelegateInterface< _ret (_decl_params) >					Interface; \
			typedef typename Interface::ptr_t									ptr_t; \
			\
		private: \
			PFunction_t		_func; \
			class_ptr_t		_classPtr; \
			\
		public: \
			TMemberDelegateImpl (const class_ptr_t &ptr, PFunction_t func): _classPtr(ptr), _func(func) {} \
			\
			bool		IsValid ()				const override	{ return _func != null and _classPtr != null; } \
			_ret		Call (_decl_params_ref)	const override	{ return ((*_classPtr).*_func)( _func_args ); } \
			void		CloneTo (ptr_t &p)		const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			TypeId_t	TypeId ()				const override	{ return TypeIdOf( *this ); } \
			usize		Size ()					const override	{ return sizeof( this ); } \
		}; \
		\
		/* Delegate Implementation */ \
		template <typename C, _template_params> \
		struct TMemberConstDelegateImpl _template_override : \
			TDelegateInterface##_uid< typename RawPointer< C >::type _template_types_var_with_comma > \
		{ \
		public: \
			typedef typename RawPointer<C>::type								class_t; \
			typedef _ret (class_t:: * PFunction_t)( _decl_params ) const; \
			typedef TMemberConstDelegateImpl< C _template_types_with_comma >	Self; \
			typedef typename RawPointer< C >::ptr_t								class_ptr_t; \
			typedef TDelegateInterface< _ret (_decl_params) >					Interface; \
			typedef typename Interface::ptr_t									ptr_t; \
			\
		private: \
			PFunction_t		_func; \
			class_ptr_t		_classPtr; \
			\
		public: \
			TMemberConstDelegateImpl (const class_ptr_t &ptr, PFunction_t func): _classPtr(ptr), _func(func) {} \
			\
			bool		IsValid ()				const override	{ return _func != null and _classPtr != null; } \
			_ret		Call (_decl_params_ref)	const override	{ return ((*_classPtr).*_func)( _func_args ); } \
			void		CloneTo (ptr_t &p)		const override	{ p._SetPtr( new ( p._GetBuffer< sizeof(Self) >() ) Self( *this ) ); } \
			TypeId_t	TypeId ()				const override	{ return TypeIdOf( *this ); } \
			usize		Size ()					const override	{ return sizeof( this ); } \
		}; \
	} \
	\
	namespace DelegateBuilder \
	{ \
		template <typename C, typename CP, _template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			typedef _types_hidden_::TMemberDelegateImpl< CP _template_types_with_comma >	del_impl_t; \
			del._func._SetPtr( new ( del._func._GetBuffer< sizeof(del_impl_t) >() ) del_impl_t( ptr, func ) ); \
		} \
		\
		template <typename C, typename CP, _template_params> \
		inline void Create (OUT TDelegate < _ret (_decl_params) > &del, const CP &ptr, _ret (C:: *func) (_decl_params) const) \
		{ \
			typedef _types_hidden_::TMemberConstDelegateImpl< CP _template_types_with_comma >	del_impl_t; \
			del._func._SetPtr( new ( del._func._GetBuffer< sizeof(del_impl_t) >() ) del_impl_t( ptr, func ) ); \
		} \
		\
		template <typename C, typename CP, _template_params> \
		inline TDelegate < _ret (_decl_params) >  Create (const CP &ptr, _ret (C:: *func) (_decl_params)) \
		{ \
			TDelegate < _ret (_decl_params) >	del; \
			Create( del, ptr, func ); \
			return del; \
		} \
		\
		template <typename C, typename CP, _template_params> \
		inline TDelegate < _ret (_decl_params) >  Create (const CP &ptr, _ret (C:: *func) (_decl_params) const) \
		{ \
			TDelegate < _ret (_decl_params) >	del; \
			Create( del, ptr, func ); \
			return del; \
		} \
	}


#define FUNCTION_FIRST_DECL( _template_params, \
							 _template_types, \
							 _template_types_var, \
							 _ret, \
							 _decl_params, \
							 _decl_params_with_ref, \
							 _member_params, \
							 _args_to_members, \
							 _members_move_ctor, \
							 _arg_params, \
							 _func_args, \
							 _uid ) \
	\
	_STATICFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								, \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(, _decl_params_with_ref), \
								ARGS(_member_params), \
								ARGS(, _args_to_members), \
								ARGS(, _members_move_ctor), \
								ARGS(_arg_params), \
								ARGS(, _func_args) ) \
	\
	_STATICDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								, \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args) ) \
	\
	_EVENTDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args) ) \
	\
	_MEMBERFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								, \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(, _decl_params_with_ref), \
								ARGS(_member_params), \
								ARGS(, _args_to_members), \
								ARGS(, _members_move_ctor), \
								ARGS(_arg_params), \
								ARGS(, _func_args) ) \
	\
	_MEMBERDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								, \
								ARGS(, _template_types), \
								ARGS(, _template_types_var), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args), \
								_uid )


#define FUNCTION_TYPE_DECL( _template_params, \
							_template_types, \
							_template_types_var, \
							_ret, \
							_decl_params, \
							_decl_params_with_ref, \
							_member_params, \
							_args_to_members, \
							_members_move_ctor, \
							_arg_params, \
							_func_args, \
							_uid ) \
	\
	_STATICFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<BufSize, _template_types>), \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(, _decl_params_with_ref), \
								ARGS(_member_params), \
								ARGS(, _args_to_members), \
								ARGS(, _members_move_ctor), \
								ARGS(_arg_params), \
								ARGS(, _func_args) ) \
	\
	_STATICDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<_template_types>), \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args) ) \
	\
	_EVENTDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args) ) \
	\
	_MEMBERFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<C, CP, BufSize, _template_types>), \
								ARGS(_template_types), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(, _decl_params_with_ref), \
								ARGS(_member_params), \
								ARGS(, _args_to_members), \
								ARGS(, _members_move_ctor), \
								ARGS(_arg_params), \
								ARGS(, _func_args) ) \
	\
	_MEMBERDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<C, _template_types>), \
								ARGS(, _template_types), \
								ARGS(, _template_types_var), \
								_ret, \
								ARGS(_decl_params), \
								ARGS(_decl_params_with_ref), \
								ARGS(_func_args), \
								_uid )

#define FUNCTION_TYPE_DECL_NO_ARGS( _template_params, \
									_template_types, \
									_template_types_var, \
									_ret, \
									_decl_params, \
									_decl_params_with_ref, \
									_member_params, \
									_args_to_members, \
									_members_move_ctor, \
									_arg_params, \
									_func_args, \
									_uid ) \
	\
	_STATICFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<BufSize, _template_types>), \
								ARGS(_template_types), \
								_ret, \
								, \
								, \
								, \
								, \
								, \
								, \
								) \
	\
	_STATICDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<_template_types>), \
								ARGS(_template_types), \
								_ret, \
								, \
								, \
								) \
	\
	_EVENTDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								_ret, \
								, \
								, \
								) \
	\
	_MEMBERFUNCTION_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<C, CP, BufSize, _template_types>), \
								ARGS(_template_types), \
								_ret, \
								, \
								, \
								, \
								, \
								, \
								, \
								) \
	\
	_MEMBERDELEGATE_TYPE_DECL(	ARGS(_template_params), \
								ARGS(<C, _template_types>), \
								ARGS(, _template_types), \
								ARGS(, _template_types_var), \
								_ret, \
								, \
								, \
								, \
								_uid )

#define UNREF( _t )		typename _types_hidden_::RemoveReference<_t>::type
#define REF( _t )		typename _types_hidden_::AddConstReference<_t>::type
#define MOVE( _v )		_v( ToRValueRef( o._v ) )

#define TDelegate		delegate
#define TFunction		function
#define TEventDelegate	event


	namespace _types_hidden_
	{
		//
		// Remove Reference qualifiers (for function class fields)
		//

		template <typename T>
		struct RemoveReference {
			typedef T			type;
		};

		template <typename T>
		struct RemoveReference <const T &> {
			typedef const T		type;
		};

		template <typename T>
		struct RemoveReference <T &> {
			typedef void			type;	// reference not supported
		};


		//
		// Add Const Reference qualifiers (for function and delegate arguments)
		//

		template <typename T>
		struct AddConstReference {
			typedef typename SwitchType< (sizeof(T) > sizeof(void*)), const T &, T >::type	type;
		};

		template <typename T>
		struct AddConstReference <const T &> {
			typedef const T &		type;
		};

		template <typename T>
		struct AddConstReference <T &> {
			typedef T &				type;	// reference supported only for delegates
		};


		//
		// Delegate Interface
		//

		template <typename Func>
		struct TDelegateInterface {};
	

		//
		// Raw Pointer type
		//

		template <typename T>	struct RawPointer		{ typedef typename T::value_t	type;	typedef T		ptr_t; };
		template <typename T>	struct RawPointer<T *>	{ typedef T						type;	typedef Ptr<T>	ptr_t; };

	}	// _types_hidden_
		
	

	//
	// Function Builder
	//

	namespace FunctionBuilder
	{
		template <typename Func>	struct Type {};
	}



	//
	// Function
	//

	template <typename Ret, usize BufSize = UX_OPT_FUNCTION_INTERFACE_SIZE>
	struct TFunction
	{
		template <typename Func>
		friend struct FunctionBuilder::Type;

	// types
	public:
		struct Interface
		{
		// types
			typedef BufferedPtr< Interface, BufSize >	ptr_t;

		// interface
			virtual ~Interface () {}

			virtual bool		IsValid ()			const = 0;
			virtual Ret			Call ()				const = 0;
			virtual void		CloneTo (ptr_t &)	const = 0;
			virtual void		MoveTo (ptr_t &p)				{ CloneTo( p ); }
			virtual TypeId_t	TypeId ()			const = 0;
			virtual usize		Size ()				const = 0;
			
		// methods
			bool Cmp (const Interface *p) const
			{
				const usize size = Size();
				return	( size == p->Size() ) and
						( TypeId() == p->TypeId() ) and
						MemCmp( (void *)this, (void *)p, size ) == 0;
			}
			
			bool Less (const Interface *p) const
			{
				const usize		size0 = Size();
				const usize		size1 = p->Size();
				const TypeId_t	type0 = TypeId();
				const TypeId_t	type1 = p->TypeId();
				
				if ( type0 == type1 ) {
					if ( size0 == size1 )
						return MemCmp( (void *)this, (void *)p, size0 ) < 0;
					else
						return size0 < size1;
				}
				return type0 < type1;
			}
			
			bool Greater (const Interface *p) const
			{
				const usize		size0 = Size();
				const usize		size1 = p->Size();
				const TypeId_t	type0 = TypeId();
				const TypeId_t	type1 = p->TypeId();
				
				if ( type0 == type1 ) {
					if ( size0 == size1 )
						return MemCmp( (void *)this, (void *)p, size0 ) > 0;
					else
						return size0 > size1;
				}
				return type0 > type1;
			}
		};

		typedef TFunction< Ret, BufSize >	Self;
		typedef typename Interface::ptr_t	interface_ptr_t;


	// variables
	private:
		interface_ptr_t		_func;


	// methods
	public:
		TFunction () : _func()
		{}


		TFunction (const Self &other)
		{
			if ( other._func.IsNotNull() ) {
				other._func->CloneTo( _func );
			}
		}

		RVALUE_REFERENCE_ONLY(
			TFunction (Self &&other)
			{
				if ( other._func.IsNotNull() ) {
					other._func->MoveTo( _func );
				}
			}
		)
		

		Self &	operator =  (const Self &right)
		{
			if ( right._func.IsNotNull() ) {
				right._func->CloneTo( _func );
			}
			return *this;
		}


		void MoveTo (Self &other)
		{
			if ( other._func.IsNotNull() ) {
				other._func->MoveTo( _func );
			}
		}


		bool	IsValid ()						const	{ return _func.IsNotNull() and _func->IsValid(); }

		Ret		Call ()							const	{ ASSERT( IsValid() );  return _func->Call(); }
		Ret		SafeCall ()						const	{ return IsValid() ? _func->Call() : Ret(); }
		
		Ret		operator () ()					const	{ ASSERT( IsValid() );  return _func->Call(); }

		bool	operator == (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Cmp( right ); }
		bool	operator <  (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Less( right._func.ptr() ); } \
		bool	operator >  (const Self &right)	const	{ ASSERT( IsValid() );  return _func->Greater( right._func.ptr() ); } \
		bool	operator != (const Self &right)	const	{ return not (*this == right); } \
		bool	operator <= (const Self &right)	const	{ return not (*this >  right); } \
		bool	operator >= (const Self &right)	const	{ return not (*this <  right); } \
	};


	//
	// Delegate
	//

	template <typename Func>
	struct TDelegate {};

	namespace DelegateBuilder {}

				
	//
	// Event
	//

	template <typename Func>
	struct TEventDelegate {};


	//
	// Static Function & Member Function
	// Static Delegate & Member Delegate
	//
	
	FUNCTION_FIRST_DECL(
		// _template_params
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9,
				typename T10, typename T11, typename T12, typename T13, typename T14 ),
		// _template_types
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 ),
		// _template_types_var
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14 ),
		// _ret
		Ret,
		// _decl_params
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13, T14 v14 ),
		// _decl_params_with_ref
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9, REF(T10) v10, REF(T11) v11, REF(T12) v12, REF(T13) v13, REF(T14) v14 ),
		// _member_params
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9;
			  UNREF(T10) _v10; UNREF(T11) _v11; UNREF(T12) _v12; UNREF(T13) _v13; UNREF(T14) _v14; ),
		// _args_to_members
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8),
			  _v9(v9), _v10(v10), _v11(v11), _v12(v12), _v13(v13), _v14(v14) ),
		// _members_move_ctor
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7),
			  MOVE(_v8), MOVE(_v9), MOVE(_v10), MOVE(_v11), MOVE(_v12), MOVE(_v13), MOVE(_v14) ),
		// _arg_params
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10, _v11, _v12, _v13, _v14 ),
		// _func_args
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14 ),
		// _uid
		15
	);
	
	FUNCTION_TYPE_DECL(
		// _template_params
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9,
				typename T10, typename T11, typename T12, typename T13 ),
		// _template_types
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void ),
		// _template_types_var
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13 ),
		// _ret
		Ret,
		// _decl_params
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12, T13 v13 ),
		// _decl_params_with_ref
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9, REF(T10) v10, REF(T11) v11, REF(T12) v12, REF(T13) v13 ),
		// _member_params
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9;
			  UNREF(T10) _v10; UNREF(T11) _v11; UNREF(T12) _v12; UNREF(T13) _v13; ),
		// _args_to_members
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8), _v9(v9), _v10(v10), _v11(v11), _v12(v12), _v13(v13) ),
		// _members_move_ctor
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8), MOVE(_v9), MOVE(_v10), MOVE(_v11), MOVE(_v12), MOVE(_v13) ),
		// _arg_params
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10, _v11, _v12, _v13 ),
		// _func_args
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13 ),
		// _uid
		14
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9,
				typename T10, typename T11, typename T12 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11, T12 v12 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9, REF(T10) v10, REF(T11) v11, REF(T12) v12 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9;
			  UNREF(T10) _v10; UNREF(T11) _v11; UNREF(T12) _v12; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8), _v9(v9), _v10(v10), _v11(v11), _v12(v12) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8), MOVE(_v9), MOVE(_v10), MOVE(_v11), MOVE(_v12) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10, _v11, _v12 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12 ),
		13
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9,
				typename T10, typename T11 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10, T11 v11 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9, REF(T10) v10, REF(T11) v11 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9;
			  UNREF(T10) _v10; UNREF(T11) _v11; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8), _v9(v9), _v10(v10), _v11(v11) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8), MOVE(_v9), MOVE(_v10), MOVE(_v11) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10, _v11 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11 ),
		12
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9,
				typename T10 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9, T10 v10 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9, REF(T10) v10 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9;
			  UNREF(T10) _v10; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8), _v9(v9), _v10(v10) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8), MOVE(_v9), MOVE(_v10) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9, _v10 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10 ),
		11
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8, typename T9 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8, T9 v9 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7,
			  REF(T8) v8, REF(T9) v9 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; UNREF(T9) _v9; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8), _v9(v9) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8), MOVE(_v9) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8, _v9 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8, v9 ),
		10
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7, typename T8 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, T8 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7, T8 v8 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7, REF(T8) v8 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; UNREF(T8) _v8; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7), _v8(v8) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7), MOVE(_v8) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7, _v8 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7, v8 ),
		9
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6, typename T7 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, T7 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6, T7 v7 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6, REF(T7) v7 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; UNREF(T7) _v7; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6), _v7(v7) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6), MOVE(_v7) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6, _v7 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6, v7 ),
		8
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5, typename T6 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, T6 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5, T6 v6 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5, REF(T6) v6 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; UNREF(T6) _v6; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5), _v6(v6) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5), MOVE(_v6) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5, _v6 ),
		ARGS( v0, v1, v2, v3, v4, v5, v6 ),
		7
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret,
				typename T0, typename T1, typename T2, typename T3, typename T4,
				typename T5 ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4, T5 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4, T5 v5 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4, REF(T5) v5 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4;
			  UNREF(T5) _v5; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4), _v5(v5) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4), MOVE(_v5) ),
		ARGS( _v0, _v1, _v2, _v3, _v4, _v5 ),
		ARGS( v0, v1, v2, v3, v4, v5 ),
		6
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret, typename T0, typename T1, typename T2, typename T3, typename T4 ),
		ARGS( Ret, T0, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3, T4 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3, T4 v4 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3, REF(T4) v4 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; UNREF(T4) _v4; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3), _v4(v4) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3), MOVE(_v4) ),
		ARGS( _v0, _v1, _v2, _v3, _v4 ),
		ARGS( v0, v1, v2, v3, v4 ),
		5
	);

	FUNCTION_TYPE_DECL(
		ARGS( typename Ret, typename T0, typename T1, typename T2, typename T3 ),
		ARGS( Ret, T0, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2, T3 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2, T3 v3 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2, REF(T3) v3 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; UNREF(T3) _v3; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2), _v3(v3) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2), MOVE(_v3) ),
		ARGS( _v0, _v1, _v2, _v3 ),
		ARGS( v0, v1, v2, v3 ),
		4
	);
	
	FUNCTION_TYPE_DECL(
		ARGS( typename Ret, typename T0, typename T1, typename T2 ),
		ARGS( Ret, T0, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1, T2 ),
		Ret,
		ARGS( T0 v0, T1 v1, T2 v2 ),
		ARGS( REF(T0) v0, REF(T1) v1, REF(T2) v2 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; UNREF(T2) _v2; ),
		ARGS( _v0(v0), _v1(v1), _v2(v2) ),
		ARGS( MOVE(_v0), MOVE(_v1), MOVE(_v2) ),
		ARGS( _v0, _v1, _v2 ),
		ARGS( v0, v1, v2 ),
		3
	);
	
	FUNCTION_TYPE_DECL(
		ARGS( typename Ret, typename T0, typename T1 ),
		ARGS( Ret, T0, T1, void, void, void, void, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0, T1 ),
		Ret,
		ARGS( T0 v0, T1 v1 ),
		ARGS( REF(T0) v0, REF(T1) v1 ),
		ARGS( UNREF(T0) _v0; UNREF(T1) _v1; ),
		ARGS( _v0(v0), _v1(v1) ),
		ARGS( MOVE(_v0), MOVE(_v1) ),
		ARGS( _v0, _v1 ),
		ARGS( v0, v1 ),
		2
	);
	
	FUNCTION_TYPE_DECL(
		ARGS( typename Ret, typename T0 ),
		ARGS( Ret, T0, void, void, void, void, void, void, void, void, void, void, void, void, void, void ),
		ARGS( Ret, T0 ),
		Ret,
		ARGS( T0 v0 ),
		ARGS( REF(T0) v0 ),
		ARGS( UNREF(T0) _v0; ),
		ARGS( _v0(v0) ),
		ARGS( MOVE(_v0) ),
		ARGS( _v0 ),
		ARGS( v0 ),
		1
	);

	FUNCTION_TYPE_DECL_NO_ARGS(
		typename Ret,
		ARGS( Ret, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void ),
		Ret,
		Ret,
		,
		,
		,
		,
		,
		,
		,
		0
	);
	

#undef UNREF
#undef TFunction
#undef TDelegate
#undef TEventDelegate
#undef _STATICFUNCTION_TYPE_DECL
#undef _STATICDELEGATE_TYPE_DECL
#undef _EVENTDELEGATE_TYPE_DECL
#undef _MEMBERFUNCTION_TYPE_DECL
#undef _MEMBERDELEGATE_TYPE_DECL
#undef FUNCTION_FIRST_DECL
#undef FUNCTION_TYPE_DECL
#undef FUNCTION_TYPE_DECL_NO_ARGS

//-------------------------------------------------------------------

}	// UXTypes
}	// UX_STL

#endif	// _UXS_FUNCTION_H